home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fsstat / RCS / fsstat.c,v < prev    next >
Encoding:
Text File  |  1992-05-15  |  31.3 KB  |  1,081 lines

  1. head     1.8;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.8
  10. date     92.05.15.11.10.08;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.7;
  13.  
  14. 1.7
  15. date     89.10.10.10.17.22;  author brent;  state Exp;
  16. branches ;
  17. next     1.6;
  18.  
  19. 1.6
  20. date     89.08.29.15.11.20;  author jhh;  state Exp;
  21. branches ;
  22. next     1.5;
  23.  
  24. 1.5
  25. date     89.06.15.17.46.03;  author brent;  state Exp;
  26. branches ;
  27. next     1.4;
  28.  
  29. 1.4
  30. date     89.02.15.09.23.36;  author brent;  state Exp;
  31. branches ;
  32. next     1.3;
  33.  
  34. 1.3
  35. date     89.02.09.10.59.12;  author brent;  state Exp;
  36. branches ;
  37. next     1.2;
  38.  
  39. 1.2
  40. date     89.02.09.09.52.41;  author brent;  state Exp;
  41. branches ;
  42. next     1.1;
  43.  
  44. 1.1
  45. date     88.12.02.09.05.53;  author brent;  state Exp;
  46. branches ;
  47. next     ;
  48.  
  49.  
  50. desc
  51. @Program to print file system statistics
  52. @
  53.  
  54.  
  55. 1.8
  56. log
  57. @Lint.  Use <> syntax for includes.  Avoid a couple possible divisions
  58. by zero.
  59. @
  60. text
  61. @/* 
  62.  * fsstat.c --
  63.  *
  64.  *    Print out the statistics kept for the filesystem.
  65.  *
  66.  * Copyright (C) 1986 Regents of the University of California
  67.  * All rights reserved.
  68.  */
  69.  
  70. #ifndef lint
  71. static char rcsid[] = "$Header: /sprite/src/cmds/fsstat/RCS/fsstat.c,v 1.7 89/10/10 10:17:22 brent Exp Locker: kupfer $ SPRITE (Berkeley)";
  72. #endif not lint
  73.  
  74. #include <sprite.h>
  75. #include <fs.h>
  76. #include <fsCmd.h>
  77. #include <stdio.h>
  78. #include <option.h>
  79. #include <vm.h>
  80. #include <sysStats.h>
  81. #include <kernel/vm.h>
  82. #include <kernel/fs.h>
  83. #include <kernel/fsStat.h>
  84.  
  85. Boolean deleteHist = FALSE;
  86. Boolean printHostInfo = FALSE;
  87. /*
  88.  * Parameters for printing histogram.  This will catch all times we'll
  89.  * encounter and will fit everything in an 80-column screen.  The program
  90.  * will still check for non-zero values outside this region and print
  91.  * a warning if one is encountered.  DEFAULT_WIDTH is 79 since we'd rather
  92.  * not print in the last column, and each entry takes 5 chars.
  93.  */
  94.  
  95. #define DEFAULT_WIDTH 79
  96.  
  97. int printExtraFileStats = FALSE;
  98. int numTimesToPrint = FS_HIST_TIME_BUCKETS; /* by default, print everything. */
  99. int numSizesToPrint = DEFAULT_WIDTH/5;
  100.  
  101. Option optionArray[] = {
  102.     {OPT_TRUE, "d", (Address)&deleteHist, "Print deletion histogram"},
  103.     {OPT_TRUE, "H", (Address)&printHostInfo, "Print kernel version and uptime info"},
  104.     {OPT_TRUE, "F", (Address)&printExtraFileStats, "Print file life-time info"},
  105.     {OPT_INT, "T", (Address)&numTimesToPrint,
  106.          "Number of times for which to print data"},
  107.     {OPT_INT, "S", (Address)&numSizesToPrint,
  108.          "Number of sizes for which to print data"},
  109. };
  110. int numOptions = sizeof(optionArray) / sizeof(Option);
  111.  
  112. ReturnStatus status;
  113.  
  114. Fs_Stats fsStats;
  115. Vm_Stat    vmStats;
  116. Fs_TypeStats fsTypeStats;
  117.  
  118. int GetRatio();
  119.  
  120. #define PrintRatio(x,y) printf("  %11d %3d%%", (x), GetRatio((x), (y)))
  121.  
  122. main(argc, argv)
  123.     int argc;
  124.     char *argv[];
  125. {
  126.     int status = SUCCESS;
  127.     register int t1;
  128.     int i;
  129.     unsigned int vmBlocksWritten;
  130.     unsigned int vmBlocksRead;
  131.     int pageSize;
  132.     char          version[128];
  133.     char          hostname[128];
  134.     double overflowFactor;
  135.  
  136.     argc = Opt_Parse(argc, argv, optionArray, numOptions);
  137.  
  138.     /*
  139.      * For "pseudo-double" variables -- two integers -- we need to store
  140.      * them in this program as real double variables.  The problem is,
  141.      * we can't just convert 0x80000000 from an unsigned int to float, because
  142.      * our C compiler goofs and makes the result negative.  Therefore, some
  143.      * tricks to take the FS_STAT_OVERFLOW constant and turn it into a number
  144.      * we can use to multiply by the overflow counter.  Shift it right, then
  145.      * multiply it by the equivalent number once it's a "double".  
  146.      *
  147.      * Note: the definition of FS_STAT_OVERFLOW confuses the gcc compiler
  148.      *    and results in a negative value of overflowFactor if used directly,
  149.      *    even after shifting and multiplying.  The definition is:
  150.      *    FS_STAT_OVERFLOW (1 << (sizeof(unsigned int) * 8 - 1))
  151.      */
  152.     overflowFactor = (0x80000000 >> 1) * 2.0;
  153.     
  154.     if (printHostInfo) {
  155.     if (Sys_Stats(SYS_GET_VERSION_STRING, sizeof(version), version) ==
  156.         SUCCESS){
  157.         printf("Kernel version: %s\n", version);
  158.     }
  159.     fflush(stdout);
  160.     (void)system("date;loadavg");
  161.     }
  162.  
  163.     status = Fs_Command(FS_RETURN_STATS, sizeof(Fs_Stats), &fsStats);
  164.     if (status != SUCCESS) {
  165.     Stat_PrintMsg(status, "Fs_Command failed");
  166.     exit(status);
  167.     }
  168.     status = Vm_Cmd(VM_GET_STATS, &vmStats);
  169.     if (status != SUCCESS) {
  170.     Stat_PrintMsg(status, "Vm_Cmd failed");
  171.     exit(status);
  172.     }
  173.     Vm_PageSize(&pageSize);
  174.     vmBlocksWritten = vmStats.pagesWritten * (pageSize / FS_BLOCK_SIZE);
  175.     if (printExtraFileStats) {
  176.     status = Fs_Command(FS_RETURN_LIFE_TIMES, sizeof(Fs_TypeStats), &fsTypeStats);
  177.     if (status != SUCCESS) {
  178.         fprintf(stderr, "This kernel doesn't do FS_RETURN_LIFE_TIMES\n");
  179.         printExtraFileStats = 0;
  180.     }
  181.     }
  182.  
  183.  
  184.   {
  185.     register Fs_BlockCacheStats *block;
  186.     
  187.     block = &fsStats.blockCache;
  188.     printf("Block Cache, %.2f Mbytes\n", (float)block->numCacheBlocks *
  189.                 FS_BLOCK_SIZE / (1024 * 1024));
  190.     printf(" BLOCKS %u min %u max %u(%u) free %u\n",
  191.         block->numCacheBlocks, block->minCacheBlocks,
  192.         block->maxCacheBlocks, block->maxNumBlocks,
  193.         block->numFreeBlocks);
  194.     t1 = block->readHitsOnDirtyBlock + block->readHitsOnCleanBlock;
  195.     printf(" READS   %8u dr_hits %8u cl_hits  %8u\t\thit ratio %u\n",
  196.         block->readAccesses,
  197.         block->readHitsOnDirtyBlock,
  198.         block->readHitsOnCleanBlock,
  199.         100 * t1 / block->readAccesses);
  200.     printf(" WRITES  %8u  p-hits %8u p-misses %8u\t\ttfc ratio %u\n",
  201.         block->writeAccesses,
  202.         block->partialWriteHits,
  203.         block->partialWriteMisses,
  204.         block->writeAccesses ?
  205.         100 * block->blocksWrittenThru / block->writeAccesses : 0);
  206.     printf(" WRITETHRU %u ", block->blocksWrittenThru);
  207.     if (block->blocksWrittenThru) {
  208.     printf("data %u %u%% index %u %u%% desc %u %u%% dir %u %u%% vm %u %u%%\n",
  209.         block->dataBlocksWrittenThru,
  210.         100 * block->dataBlocksWrittenThru / block->writeAccesses,
  211.         block->indBlocksWrittenThru,
  212.         100 * block->indBlocksWrittenThru / block->writeAccesses,
  213.         block->descBlocksWrittenThru,
  214.         100 * block->descBlocksWrittenThru / block->writeAccesses,
  215.         block->dirBlocksWrittenThru,
  216.         100 * block->dirBlocksWrittenThru / block->writeAccesses,
  217.         vmBlocksWritten,
  218.         100 * vmBlocksWritten / block->writeAccesses);
  219.     }
  220.     printf(" ZERO FILL read %u write %u/%u append %u over %u\n",
  221.         block->readZeroFills,
  222.         block->writeZeroFills1, block->writeZeroFills2,
  223.         block->appendWrites,
  224.         block->overWrites);
  225.     printf(" READ AHEAD %u hits %u all in cache %u/%u\t\t\thit ratio %u\n",
  226.         block->readAheads,
  227.         block->readAheadHits,
  228.         block->allInCacheCalls,
  229.         block->allInCacheTrue,
  230.         block->readAheads ?
  231.         100 * block->readAheadHits / block->readAheads : 0);
  232.     printf(" FRAGMENT upgrades %u hits %u zero fills %u\n",
  233.         block->fragAccesses,
  234.         block->fragHits,
  235.         block->fragZeroFills);
  236.     if (block->fileDescReads > 0) {
  237.     printf(" FILE DESC reads %u hits %u (%2u%%) writes %u hits %u (%2u%%)\n", 
  238.             block->fileDescReads, block->fileDescReadHits,
  239.             100 * block->fileDescReadHits / block->fileDescReads,
  240.             block->fileDescWrites, block->fileDescWriteHits,
  241.             block->fileDescWrites ?
  242.             100 * block->fileDescWriteHits / block->fileDescWrites
  243.             : 0);
  244.     }
  245.     if (block->indBlockAccesses > 0) {
  246.     printf(" INDIRECT BLOCKS  Accesses %u hits %u\t\t\thit ratio %u\n", 
  247.             block->indBlockAccesses, block->indBlockHits,
  248.             100 * block->indBlockHits / block->indBlockAccesses);
  249.     }
  250.     if (block->dirBlockAccesses > 0) {
  251.     printf(" DIRECTORY BLOCKS Accesses %u hits %u\t\t\thit ratio %u\n", 
  252.             block->dirBlockAccesses, block->dirBlockHits,
  253.             100 * block->dirBlockHits / block->dirBlockAccesses);
  254.     }
  255.     printf(" VM asked %u we tried %u gave up %u Pitched %u\n",
  256.         block->vmRequests, block->triedToGiveToVM, block->vmGotPage,
  257.         block->blocksPitched);
  258.     printf(" ALLOC from free %u new %u lru %u part free %u\n",
  259.         block->totFree, block->unmapped,
  260.         block->lru, block->partFree);
  261.   }
  262.   {
  263.     register Fs_AllocStats *alloc = &fsStats.alloc;
  264.     if (alloc->blocksAllocated > 0) {
  265.     printf("Block Allocation Statistics:\n");
  266.     printf(" BLOCKS alloc %u free %u\n", alloc->blocksAllocated,
  267.            alloc->blocksFreed);
  268.     printf(" CYLINDERS searched %u hashes %u bit-searches %u\n",
  269.            alloc->cylsSearched, alloc->cylHashes,
  270.            alloc->cylBitmapSearches);
  271.     printf(
  272. " FRAGS alloc %u free %u fr->block %u block->fr %u upgrades %u bad hints %u\n",
  273.            alloc->fragsAllocated, alloc->fragsFreed,
  274.            alloc->fragToBlock, alloc->fullBlockFrags,
  275.            alloc->fragUpgrades, alloc->badFragList);
  276.     }
  277.   }
  278.   {
  279.     register Fs_NameOpStats *cltName = &fsStats.cltName;
  280.     printf("Client Naming Operations:\n");
  281.     printf(" Open R %u W %u RW %u chdir %d\n",
  282.         cltName->numReadOpens, cltName->numWriteOpens,
  283.         cltName->numReadWriteOpens,
  284.         cltName->chdirs);
  285.     printf(" Make dir %u dev %u hardLink %u symLink %u\n",
  286.         cltName->makeDirs, cltName->makeDevices,
  287.         cltName->hardLinks, cltName->symLinks);
  288.     printf(" Remove %u rename %u rmdir %u\n",
  289.         cltName->removes, cltName->renames,
  290.         cltName->removeDirs);
  291.     printf(" Get attr name %u stream %u Set attr name %u stream %u\n",
  292.         cltName->getAttrs, cltName->getAttrIDs,
  293.         cltName->setAttrs, cltName->setAttrIDs);
  294.   }
  295.   {
  296.     register Fs_NameOpStats *srvName = &fsStats.srvName;
  297.     if (srvName->numReadOpens > 0) {
  298.     printf("Server Naming Operations:\n");
  299.     printf(" Opens %u\n",
  300.             srvName->numReadOpens);
  301.     printf(" Make dir %u dev %u hardLink %u symLink %u\n",
  302.             srvName->makeDirs, srvName->makeDevices,
  303.             srvName->hardLinks, srvName->symLinks);
  304.     printf(" Remove %u rename %u rmdir %u\n",
  305.             srvName->removes, srvName->renames,
  306.             srvName->removeDirs);
  307.     printf(" Get attr name %u stream %u Set attr name %u stream %u\n",
  308.             srvName->getAttrs, srvName->getAttrIDs,
  309.             srvName->setAttrs, srvName->setAttrIDs);
  310.     printf(" Get I/O attr %u Set I/O attr %u\n",
  311.             srvName->getIOAttrs, srvName->setIOAttrs);
  312.     }
  313.   }
  314.   {
  315.     register Fs_LookupStats *lookup = &fsStats.lookup;
  316.     register Fs_NameCacheStats *name = &fsStats.nameCache;
  317.     register int lookupMisses;
  318.     if (lookup->number > 0) {
  319.     printf("Name Lookup Statistics:\n");
  320.     lookupMisses = lookup->notFound + lookup->redirect +
  321.              lookup->remote + lookup->parent;
  322.     printf(" Paths %u hits %d (%u%%) components %u avg %.2f $MACHINE %u\n",
  323.         lookup->number, lookup->number - lookupMisses,
  324.         100 * (lookup->number - lookupMisses) / lookup->number,
  325.         lookup->numComponents,
  326.         (float)lookup->numComponents / (float)lookup->number,
  327.         lookup->numSpecial);
  328.     printf(" For create %u delete %u link %u rename %u\n",
  329.         lookup->forCreate, lookup->forDelete,
  330.         lookup->forLink, lookup->forRename);
  331.     printf(" Not found %u link expand %u redirect %u remote %u parent %u\n",
  332.         lookup->notFound, lookup->symlinks,
  333.         lookup->redirect, lookup->remote, lookup->parent);
  334.     }
  335.     if (name->accesses > 0) {
  336.     printf(" Name Cache tries %u hits %u (%u%%) replaced %u (%u%%) size %u\n",
  337.            name->accesses, name->hits,
  338.            100 * name->hits / name->accesses,
  339.            name->replacements,
  340.            100 * name->replacements / name->accesses,
  341.            name->size);
  342.     }
  343.   }
  344.   {
  345.     register Fs_HandleStats *handle = &fsStats.handle;
  346.     printf("File Handle Statistics:\n");
  347.     printf(" Number %u create %u install %u hits %u version %u flush %u\n",
  348.            handle->exists, handle->created, handle->installCalls,
  349.            handle->installHits, handle->versionMismatch,
  350.            handle->cacheFlushes);
  351.     printf(" Fetch %u hits %u lock %u waits %u unlock %u release %u\n",
  352.            handle->fetchCalls, handle->fetchHits, handle->locks,
  353.            handle->lockWaits, handle->unlocks, handle->release);
  354.     printf(" Segment fetches %u hits %u\t\t\t\thit ratio %u\n",
  355.            handle->segmentFetches, handle->segmentHits,
  356.            GetRatio(handle->segmentHits, handle->segmentFetches));
  357.   }
  358.   {
  359.     register Fs_PrefixStats *prefix = &fsStats.prefix;
  360.     printf("Prefix Statistics:\n");
  361.     printf(" Absolute %u relative %u redirect %u loop %u timeout %u stale %u found %u\n",
  362.            prefix->absolute, prefix->relative, prefix->redirects,
  363.            prefix->loops, prefix->timeouts, prefix->stale, prefix->found);
  364.   }
  365.  
  366.   {
  367.     unsigned int    numBytes;
  368.     unsigned int    arr[3];
  369.  
  370.     status = Fs_Command(FS_GET_FRAG_INFO, sizeof(arr), arr);
  371.     if (status != SUCCESS) {
  372.     Stat_PrintMsg(status, "Call to Fs_Command for frag info failed");
  373.     exit(status);
  374.     }
  375.     numBytes = arr[0] * FS_BLOCK_SIZE;
  376.     printf("Internal fragmentation statistics: Total bytes %u\n", numBytes);
  377.     printf(" Total bytes wasted   %7u percent %u\n",
  378.         arr[1], arr[1] * 100 / numBytes);
  379.     printf(" Waste relative to 1K %7u percent %u\n",
  380.         arr[2], arr[2] * 100 / numBytes);
  381.   }
  382. #define NUM_BYTE_COUNT_COLUMNS 4
  383.  
  384.   {
  385.       register Fs_GeneralStats *gen = &fsStats.gen;
  386.       double cacheBytes, thruBytes;
  387.       double rmtRatio, diskRatio;
  388.     
  389.       printf("Bytes:      cache     remote           disk       raw disk        devices\n");
  390.       cacheBytes = fsStats.blockCache.bytesRead +
  391.           overflowFactor * fsStats.blockCache.bytesReadOverflow;
  392.       thruBytes = gen->remoteBytesRead +
  393.           overflowFactor * gen->remoteReadOverflow;
  394.       rmtRatio = (cacheBytes > 0) ? (100. * thruBytes / cacheBytes) : 0;
  395.       printf(" Mb Read  %8.2f %8.2f %3d%%", cacheBytes / (1024 * 1024),
  396.            thruBytes / (1024 * 1024), (unsigned int)rmtRatio);
  397.  
  398.       thruBytes = gen->fileBytesRead + overflowFactor * gen->fileReadOverflow;
  399.       diskRatio = (cacheBytes > 0) ? (100. * thruBytes / cacheBytes) : 0;
  400.       printf(" %8.2f %3d%%", thruBytes / (1024 * 1024),
  401.                   (unsigned int)diskRatio);
  402.  
  403.       thruBytes = gen->physBytesRead;
  404.       diskRatio = (cacheBytes > 0) ? (100. * thruBytes / cacheBytes) : 0;
  405.  
  406.       printf(" %8.2f %3d%%", thruBytes / (1024 * 1024),
  407.                   (unsigned int)diskRatio);
  408.  
  409.       printf(" %8.2f\n", (float)gen->deviceBytesRead / (1024 * 1024));
  410.  
  411.       cacheBytes = fsStats.blockCache.bytesWritten +
  412.           overflowFactor * fsStats.blockCache.bytesWrittenOverflow;
  413.       thruBytes = gen->remoteBytesWritten +
  414.           overflowFactor * gen->remoteWriteOverflow;
  415.       if (cacheBytes > 0) {
  416.       rmtRatio = 100. * thruBytes / cacheBytes;
  417.       } else {
  418.       rmtRatio = 0.;
  419.       }
  420.       printf(" Mb Write %8.2f %8.2f %3d%%", cacheBytes / (1024 * 1024),
  421.            thruBytes / (1024 * 1024), (unsigned int)rmtRatio);
  422.       thruBytes = gen->fileBytesWritten +
  423.           overflowFactor * gen->fileWriteOverflow;
  424.       if (fsStats.blockCache.bytesWritten > 0) {
  425.       diskRatio = 100. * thruBytes / cacheBytes;
  426.       } else {
  427.       diskRatio = 0.;
  428.       }
  429.       printf(" %8.2f %3d%%", thruBytes / (1024 * 1024),
  430.               (unsigned int)diskRatio);
  431.  
  432.       thruBytes = gen->physBytesWritten;
  433.       if (cacheBytes > 0) {
  434.       diskRatio = 100. * thruBytes / cacheBytes;
  435.       } else {
  436.       diskRatio = 0.;
  437.       }
  438.       printf(" %8.2f %3d%%", thruBytes / (1024 * 1024), (unsigned int)diskRatio);
  439.       printf(" %8.2f\n", (float)gen->deviceBytesWritten / (1024 * 1024));
  440.  
  441.       printf("OBJECTS stream %d (clt %d) file %d dir %d rmtFile %d ioClt %d\n",
  442.         fsStats.object.streams, fsStats.object.streamClients,
  443.         fsStats.object.files, fsStats.object.directory,
  444.         fsStats.object.rmtFiles, fsStats.object.fileClients);
  445.       printf("OBJECTS  pipe %d dev %d pdevCtrl %d pdev %d remote %d Total %d\n",
  446.         fsStats.object.pipes, fsStats.object.devices,
  447.         fsStats.object.controls,
  448.         fsStats.object.pseudoStreams, fsStats.object.remote,
  449.         fsStats.object.streams + fsStats.object.files +
  450.         fsStats.object.directory +
  451.         fsStats.object.rmtFiles + fsStats.object.pipes +
  452.         fsStats.object.devices + fsStats.object.controls +
  453.         2 * fsStats.object.pseudoStreams + fsStats.object.remote);
  454.       printf("HANDLES %d (%d) limbo %d scav %d (dirs %d) looks/scav %.2f\n",
  455.         fsStats.handle.exists,
  456.         fsStats.handle.maxNumber,
  457.         fsStats.handle.limbo,
  458.         fsStats.handle.lruHits,
  459.         fsStats.object.dirFlushed,
  460.          (fsStats.handle.lruScans != 0
  461.           ? ((float)fsStats.handle.lruChecks /
  462.          (float)fsStats.handle.lruScans)
  463.           : 0.0));
  464.   }
  465.   {
  466.       register Fs_RecoveryStats *recovPtr = &fsStats.recovery;
  467.       if (recovPtr->number > 0 || recovPtr->wants > 0) {
  468.       printf("RECOVERED %d times, wants %d ok %d bad %d abort %d\n",
  469.           recovPtr->number, recovPtr->wants, recovPtr->waitOK,
  470.           recovPtr->waitFailed, recovPtr->waitAbort);
  471.       printf("RECOVERED %d handles, %d failed %d timed out\n",
  472.           recovPtr->succeeded, recovPtr->failed, recovPtr->timeout);
  473.       }
  474.       if ((recovPtr->clientRecovered + recovPtr->clientCrashed) > 0) {
  475.       printf("CLIENTS %d crashed, %d reopened\n", recovPtr->clientCrashed,
  476.           recovPtr->clientRecovered);
  477.       }
  478.   }
  479.   /*
  480.    * ONLY FILE TYPE I/O AND DELETION STUFF BELOW HERE
  481.    */
  482.   if (!printExtraFileStats) {
  483.       exit(status);
  484.   } else {
  485.       register Fs_TypeStats *type = &fsTypeStats;
  486.       register Fs_GeneralStats *gen = &fsStats.gen;
  487.       int ratio;
  488.       static char *typeStrings[] = { "temp", "swap", "obj", "bin", "other"};
  489.       /*
  490.        * # of columns for type-specific counts
  491.        */
  492.       unsigned int byteTotals[NUM_BYTE_COUNT_COLUMNS];
  493.  
  494.  
  495.       printf(
  496.            "File type       Cache(R)          Cache(W)           Disk(R)           Disk(W)");
  497.  
  498.       /*
  499.        * Calculate the totals for each column so we can get accurate fractions
  500.        * on a per-filetype basis.
  501.        */
  502.       
  503.       for (i = 0; i < NUM_BYTE_COUNT_COLUMNS; i++) {
  504.       byteTotals[i] = 0;
  505.       }
  506.       for (i = 0; i < FS_STAT_NUM_TYPES; i++) {
  507.       byteTotals [0] += type->cacheBytes[FS_STAT_READ][i];
  508.       byteTotals [1] += type->cacheBytes[FS_STAT_WRITE][i];
  509.       byteTotals [2] += type->diskBytes[FS_STAT_READ][i];
  510.       byteTotals [3] += type->diskBytes[FS_STAT_WRITE][i];
  511.       }
  512.  
  513.       for (i = 0; i < FS_STAT_NUM_TYPES; i++) {
  514.       printf("\n%-6s ", typeStrings[i]);
  515.       PrintRatio(type->cacheBytes[FS_STAT_READ][i], byteTotals[0]);
  516.       PrintRatio(type->cacheBytes[FS_STAT_WRITE][i], byteTotals[1]);
  517.       PrintRatio(type->diskBytes[FS_STAT_READ][i], byteTotals[2]);
  518.       PrintRatio(type->diskBytes[FS_STAT_WRITE][i], byteTotals[3]);
  519.       }
  520.       if (gen->fileBytesDeleted > 0) {
  521.       printf("\n\nFile type      Deleted");
  522.       for (i = 0; i < FS_STAT_NUM_TYPES; i++) {
  523.           printf("\n%-5s    ", typeStrings[i]);
  524.           PrintRatio(type->bytesDeleted[i],
  525.              gen->fileBytesDeleted);
  526.       }
  527.       printf("\nTotal       %10u 100%%\n", gen->fileBytesDeleted);
  528.       } else {
  529.       printf("\n 0 bytes deleted from local disks.\n");
  530.       }
  531.       if (deleteHist && gen->fileBytesDeleted > 0) {
  532.       register int timeIndex, sizeIndex;
  533.       int fileType;
  534.       unsigned int cumBySize[FS_HIST_SIZE_BUCKETS];
  535.       unsigned int cumByTime[FS_HIST_TIME_BUCKETS];
  536.       unsigned int cumBySizeType[FS_HIST_SIZE_BUCKETS][FS_STAT_NUM_TYPES];
  537.       unsigned int cumByTimeType[FS_HIST_TIME_BUCKETS][FS_STAT_NUM_TYPES];
  538.       register unsigned int rowTotal;
  539.       unsigned int total = 0;
  540. #ifdef notdef
  541.       unsigned int numBlocks;   /* number of blocks corresponding to an index */
  542. #endif
  543.       unsigned int blockCount;  /* number blocks in array at current location */
  544.       unsigned int tooBig;       /* subtotal of last few (unprintable) columns */
  545.       char separator[DEFAULT_WIDTH + 1];
  546.       static char *timeStrings[] = {
  547.           "1 sec ",
  548.           "2 secs",
  549.           "3 secs",
  550.           "4 secs",
  551.           "5 secs",
  552.           "6 secs",
  553.           "7 secs",
  554.           "8 secs",
  555.           "9 secs",
  556.           "10 secs",
  557.           "20 secs",
  558.           "30 secs",
  559.           "40 secs",
  560.           "50 secs",
  561.           "1 min ",
  562.           "2 mins",
  563.           "3 mins",
  564.           "4 mins",
  565.           "5 mins",
  566.           "6 mins",
  567.           "7 mins",
  568.           "8 mins",
  569.           "9 mins",
  570.           "10 mins",
  571.           "20 mins",
  572.           "30 mins",
  573.           "40 mins",
  574.           "50 mins",
  575.           "1 hr ",
  576.           "2 hrs",
  577.           "3 hrs",
  578.           "4 hrs",
  579.           "5 hrs",
  580.           "6 hrs",
  581.           "7 hrs",
  582.           "8 hrs",
  583.           "9 hrs",
  584.           "10 hrs",
  585.           "15 hrs",
  586.           "20 hrs",
  587.           "1 day ",
  588.           "2 days",
  589.           "3 days",
  590.           "4 days",
  591.           "5 days",
  592.           "6 days",
  593.           "7 days",
  594.           "8 days",
  595.           "9 days",
  596.           "10 days",
  597.           "20 days",
  598.           "30 days",
  599.           "40 days",
  600.           "50 days",
  601.           "60 days",
  602.           "90 days",
  603.           "120 days",
  604.           "180 days",
  605.           "240 days",
  606.           "300 days",
  607.           "360 days",
  608.           ">360 days",
  609.       };
  610.     
  611.       bzero((Address) cumBySize, sizeof (cumBySize));
  612.       bzero((Address) cumByTime, sizeof (cumByTime));
  613.       bzero((Address) cumBySizeType, sizeof (cumBySizeType));
  614.       bzero((Address) cumByTimeType, sizeof (cumByTimeType));
  615.  
  616.       /*
  617.        * May set times to be greater than actual max, since it is
  618.        * changing around in the kernel.
  619.        */
  620.       if (numTimesToPrint > FS_HIST_TIME_BUCKETS) {
  621.           numTimesToPrint = FS_HIST_TIME_BUCKETS;
  622.       }
  623.  
  624.       for (i = 0; i < DEFAULT_WIDTH; i++) {
  625.           separator[i] = '-';
  626.       }
  627.       separator[DEFAULT_WIDTH] = '\0';
  628.  
  629.       /*
  630.        * Go through the histogram and for each time, print out one line
  631.        * per file type with all the counts for that file type.
  632.        * Then print out a summary line for that time period.
  633.        * Since we only print out the first several columns, if we
  634.        * have data for files too big to display normaly, we lump them into
  635.        * a single column at the end.
  636.        */
  637.     
  638.       printf(
  639.     "\n\014\nDeletion histogram:%59s\n <= #secs   <1K <2K <4K <8K 16K ...%43s",
  640.            "Wtd", ">>  Total");
  641.       for (timeIndex = 0; timeIndex < FS_HIST_TIME_BUCKETS; timeIndex++) {
  642.           if (timeIndex < numTimesToPrint) {
  643.           printf("\n%s\n", separator);
  644.           }
  645.           for (fileType = 0; fileType < FS_STAT_NUM_TYPES; fileType ++) {
  646.           tooBig = 0;
  647.           if (timeIndex < numTimesToPrint) {
  648.               printf("%10s  ", typeStrings[fileType]);
  649.           }
  650.           if (timeIndex > 0) {
  651.               cumByTimeType[timeIndex][fileType] =
  652.                   cumByTimeType[timeIndex - 1][fileType];
  653.           }
  654.           for (sizeIndex = 0; sizeIndex < FS_HIST_SIZE_BUCKETS - 1;
  655.                sizeIndex++) {
  656.                blockCount = type->deleteHist[timeIndex][sizeIndex]
  657.                [fileType];
  658.                if (blockCount > 0) {
  659.                cumBySizeType[sizeIndex][fileType] += blockCount;
  660.                cumBySize[sizeIndex] += blockCount;
  661.                }
  662.                if ((timeIndex < numTimesToPrint) &&
  663.                (sizeIndex < numSizesToPrint - 1)) {
  664.                printf("%3u ", cumBySizeType[sizeIndex][fileType]);
  665.                } else if (blockCount > 0) {
  666.                if (sizeIndex >= numSizesToPrint - 1) {
  667.                    tooBig += blockCount;
  668.                } else {
  669.                    fprintf(stderr,
  670.                       "Warning: element <%u,%u,%u> = %u.\n",
  671.                       timeIndex, sizeIndex, fileType,
  672.                       blockCount);
  673.                }
  674.                }
  675.            }
  676.           rowTotal = type->deleteHist[timeIndex]
  677.               [FS_HIST_SIZE_BUCKETS-1][fileType];
  678.           cumByTimeType[timeIndex][fileType] += rowTotal;
  679.           total += rowTotal;
  680.           cumByTime[timeIndex] += rowTotal;
  681.           if (timeIndex < numTimesToPrint) {
  682.               printf("%3u %6u\n", tooBig,
  683.                    cumByTimeType[timeIndex][fileType]);
  684.           }
  685.           }
  686.           /*
  687.            * Print out subtotals for this time.
  688.            */
  689.           tooBig = 0;
  690.           if (timeIndex < numTimesToPrint) {
  691.           printf("%9s   ", timeStrings[timeIndex]);
  692.           for (sizeIndex = 0; sizeIndex < FS_HIST_SIZE_BUCKETS - 1;
  693.                sizeIndex++) {
  694.                if (sizeIndex < numSizesToPrint - 1) {
  695.                printf("%3u ", cumBySize[sizeIndex]);
  696.                } else if (sizeIndex >= numSizesToPrint) {
  697.                tooBig += blockCount;
  698.                }
  699.            }
  700.           printf("%3u %6u", tooBig, total);
  701.           }
  702.       }
  703.       printf("\n\014\nPercentiles for bytes deleted, by type:\n\n");
  704.       printf("      Time   %6s %6s %6s %6s %6s   Cumulative         Cum. Total\n",
  705.            typeStrings[0],  typeStrings[1],
  706.            typeStrings[2], typeStrings[3], typeStrings[4]);
  707.       for (timeIndex = 0, rowTotal = 0;
  708.            timeIndex < numTimesToPrint; timeIndex++) {
  709.            rowTotal += cumByTime[timeIndex];
  710.            printf("%10s    ", timeStrings[timeIndex]);
  711.            for (fileType = 0; fileType < FS_STAT_NUM_TYPES; fileType++) {
  712.            ratio = GetRatio(cumByTimeType[timeIndex][fileType],
  713.                   cumByTimeType[FS_HIST_TIME_BUCKETS - 1]
  714.                              [fileType]);
  715.            printf("%5u  ", ratio);
  716.            }
  717.            printf("      %5u          %9u\n",
  718.             GetRatio(rowTotal, total), rowTotal);
  719.        }
  720.       }
  721.         
  722.   }
  723.   exit(status);
  724. }
  725.  
  726.  
  727.  
  728.  
  729. /*
  730.  *----------------------------------------------------------------------
  731.  *
  732.  * GetRatio --
  733.  *
  734.  *    Given two integers, return an integer that is 100 * the quotient of
  735.  *    the two numbers, or 0 if the first number is 0, or 100 if the
  736.  *    first number is greater than the second number.
  737.  *
  738.  * Results:
  739.  *    The ratio, normalized to a percentage, is returned.
  740.  *
  741.  * Side effects:
  742.  *    None.
  743.  *
  744.  *----------------------------------------------------------------------
  745.  */
  746.  
  747. int
  748. GetRatio(numerator, denominator)
  749.     unsigned int numerator;
  750.     unsigned int denominator;
  751. {
  752.     double ratio; 
  753.             
  754.     if (numerator > denominator) { 
  755.     return(100); 
  756.     }
  757.     if (denominator > 0 && numerator > 0) { 
  758.     ratio = (100. * numerator) / denominator + 0.5;
  759.     if (ratio < 0) {
  760.         ratio = (100000. * (numerator/1000)) /
  761.             (1000. * (denominator/1000)) + 0.5;
  762.     }
  763.     } else { 
  764.     ratio = 0.; 
  765.     }
  766.     return ((int) ratio);
  767.     
  768. @
  769.  
  770.  
  771. 1.7
  772. log
  773. @Updated to new fs typedefs.  Fixed use of overflow counters.
  774. @
  775. text
  776. @d11 1
  777. a11 1
  778. static char rcsid[] = "$Header: /a/newcmds/fsstat/RCS/fsstat.c,v 1.6 89/08/29 15:11:20 jhh Exp $ SPRITE (Berkeley)";
  779. d14 10
  780. a23 10
  781. #include "sprite.h"
  782. #include "fs.h"
  783. #include "fsCmd.h"
  784. #include "stdio.h"
  785. #include "option.h"
  786. #include "vm.h"
  787. #include "sysStats.h"
  788. #include "kernel/vm.h"
  789. #include "kernel/fs.h"
  790. #include "kernel/fsStat.h"
  791. d133 1
  792. a133 1
  793.         block->numFreeBlocks, block->blocksPitched);
  794. d296 1
  795. a296 1
  796.            100 * handle->segmentHits / handle->segmentFetches);
  797. d334 1
  798. a334 1
  799.       rmtRatio = (cacheBytes > 0) ? (thruBytes / cacheBytes * 100.) : 0;
  800. d339 1
  801. a339 1
  802.       diskRatio = (cacheBytes > 0) ? (thruBytes / cacheBytes * 100.) : 0;
  803. d344 1
  804. a344 1
  805.       diskRatio = (cacheBytes > 0) ? (thruBytes / cacheBytes * 100.) : 0;
  806. d356 1
  807. a356 1
  808.       rmtRatio = thruBytes / cacheBytes * 100.;
  809. d365 1
  810. a365 1
  811.       diskRatio = thruBytes / cacheBytes * 100.;
  812. d374 1
  813. a374 1
  814.       diskRatio = thruBytes / cacheBytes * 100.;
  815. d400 4
  816. a403 1
  817.         (float)fsStats.handle.lruChecks / (float)fsStats.handle.lruScans);
  818. @
  819.  
  820.  
  821. 1.6
  822. log
  823. @Fixed include
  824. @
  825. text
  826. @d11 1
  827. a11 1
  828. static char rcsid[] = "$Header: /a/newcmds/fsstat/RCS/fsstat.c,v 1.5 89/06/15 17:46:03 brent Exp Locker: jhh $ SPRITE (Berkeley)";
  829. d54 1
  830. a54 1
  831. FsStats fsStats;
  832. d56 1
  833. a56 1
  834. FsTypeStats fsTypeStats;
  835. d83 1
  836. a83 1
  837.      * tricks to take the FSSTAT_OVERFLOW constant and turn it into a number
  838. d86 5
  839. d92 1
  840. a92 2
  841.     t1 = FSSTAT_OVERFLOW >> 4;
  842.     overflowFactor = ((double) t1) * (1 << 4);
  843. d103 1
  844. a103 1
  845.     status = Fs_Command(FS_RETURN_STATS, sizeof(FsStats), &fsStats);
  846. d116 1
  847. a116 1
  848.     status = Fs_Command(FS_RETURN_LIFE_TIMES, sizeof(FsTypeStats), &fsTypeStats);
  849. d125 1
  850. a125 1
  851.     register FsBlockCacheStats *block;
  852. d203 1
  853. a203 1
  854.     register FsAllocStats *alloc = &fsStats.alloc;
  855. d219 1
  856. a219 1
  857.     register FsNameOpStats *cltName = &fsStats.cltName;
  858. d236 1
  859. a236 1
  860.     register FsNameOpStats *srvName = &fsStats.srvName;
  861. d255 2
  862. a256 2
  863.     register FsLookupStats *lookup = &fsStats.lookup;
  864.     register FsNameCacheStats *name = &fsStats.nameCache;
  865. d285 1
  866. a285 1
  867.     register FsHandleStats *handle = &fsStats.handle;
  868. d299 1
  869. a299 1
  870.     register FsPrefixStats *prefix = &fsStats.prefix;
  871. d325 1
  872. a325 1
  873.       register FsGeneralStats *gen = &fsStats.gen;
  874. d403 1
  875. a403 1
  876.       register FsRecoveryStats *recovPtr = &fsStats.recovery;
  877. d422 2
  878. a423 2
  879.       register FsTypeStats *type = &fsTypeStats;
  880.       register FsGeneralStats *gen = &fsStats.gen;
  881. @
  882.  
  883.  
  884. 1.5
  885. log
  886. @Updated to new Fs_Stats struct
  887. @
  888. text
  889. @d11 1
  890. a11 1
  891. static char rcsid[] = "$Header: /a/newcmds/fsstat/RCS/fsstat.c,v 1.4 89/02/15 09:23:36 brent Exp $ SPRITE (Berkeley)";
  892. a22 1
  893. #ifdef not_yet
  894. a23 3
  895. #else
  896. #include "./fsStat.h"
  897. #endif
  898. @
  899.  
  900.  
  901. 1.4
  902. log
  903. @Added limbo and ioClt fields
  904. @
  905. text
  906. @d11 1
  907. a11 1
  908. static char rcsid[] = "$Header: /a/newcmds/fsstat/RCS/fsstat.c,v 1.3 89/02/09 10:59:12 brent Exp Locker: brent $ SPRITE (Berkeley)";
  909. d23 1
  910. d25 3
  911. d118 1
  912. a118 1
  913.         fprintf(stderr, "This kernel does do FS_RETURN_LIFE_TIMES\n");
  914. a126 1
  915.     printf("Block Cache Statistics:\n");
  916. d128 3
  917. a130 1
  918.     printf(" BLOCKS %u min %u max %u(%u) free %u pitched %u\n",
  919. d135 1
  920. a135 1
  921.     printf(" READ    %8u dr_hits %8u cl_hits  %8u\t\thit ratio %u\n",
  922. d140 1
  923. a140 1
  924.     printf(" WRITE   %8u  p-hits %8u p-misses %8u\t\ttfc ratio %u\n",
  925. d195 1
  926. a195 1
  927.     printf(" VM requests %u/%u/%u, FS gave up %u\n",
  928. d197 2
  929. a198 2
  930.         block->gavePageToVM);
  931.     printf(" ALLOC free %u new %u lru %u part free %u\n",
  932. a202 12
  933.     register FsNameCacheStats *name = &fsStats.nameCache;
  934.     if (name->accesses > 0) {
  935.     printf("Name Cache Statistics:\n");
  936.     printf(" Accesses %u hits %u (%u%%) replaced %u (%u%%) size %u\n",
  937.            name->accesses, name->hits,
  938.            100 * name->hits / name->accesses,
  939.            name->replacements,
  940.            100 * name->replacements / name->accesses,
  941.            name->size);
  942.     }
  943.   }
  944.   {
  945. d219 66
  946. d291 3
  947. a293 3
  948.     printf(" Fetch %u hits %u lock %u/%u waits %u release %u\n",
  949.            handle->fetchCalls, handle->fetchHits, handle->lockCalls,
  950.            handle->locks, handle->lockWaits, handle->releaseCalls);
  951. a321 5
  952.  
  953.     printf("Count of calls: open(R) %u   (W) %u   (R/W) %u   set attributes %u\n",
  954.          fsStats.gen.numReadOpens, fsStats.gen.numWriteOpens,
  955.          fsStats.gen.numReadWriteOpens, fsStats.gen.numSetAttrs);
  956.  
  957. d335 2
  958. a336 2
  959.       printf(" Read  %10u %10u %3d%%", fsStats.blockCache.bytesRead,
  960.            gen->remoteBytesRead, (unsigned int)rmtRatio);
  961. d340 2
  962. a341 1
  963.       printf(" %9u %3d%%", gen->fileBytesRead, (unsigned int)diskRatio);
  964. d346 2
  965. a347 1
  966.       printf(" %9u %3d%%", gen->physBytesRead, (unsigned int)diskRatio);
  967. d349 1
  968. a349 1
  969.       printf(" %9u\n", gen->deviceBytesRead);
  970. d355 1
  971. a355 1
  972.       if (fsStats.blockCache.bytesWritten > 0) {
  973. d360 2
  974. a361 2
  975.       printf(" Write %10u %10u %3d%%", fsStats.blockCache.bytesWritten,
  976.            gen->remoteBytesWritten, (unsigned int)rmtRatio);
  977. d369 2
  978. a370 1
  979.       printf(" %9u %3d%%", gen->fileBytesWritten, (unsigned int)diskRatio);
  980. d373 1
  981. a373 1
  982.       if (fsStats.blockCache.bytesWritten > 0) {
  983. d378 2
  984. a379 2
  985.       printf(" %9u %3d%%", gen->physBytesWritten, (unsigned int)diskRatio);
  986.       printf(" %9u\n", gen->deviceBytesWritten);
  987. d394 7
  988. a400 5
  989.       printf("HANDLES max %d exist %d limbo %d scans %d looks %d scav %d (dirs %d)\n",
  990.         fsStats.handle.maxNumber, fsStats.handle.exists,
  991.         fsStats.object.limbo,
  992.         fsStats.object.lruScans, fsStats.object.lruChecks,
  993.         fsStats.object.scavenges, fsStats.object.dirFlushed);
  994. @
  995.  
  996.  
  997. 1.3
  998. log
  999. @Changed -L to -F
  1000. @
  1001. text
  1002. @d11 1
  1003. a11 1
  1004. static char rcsid[] = "$Header: /a/newcmds/fsstat/RCS/fsstat.c,v 1.2 89/02/09 09:52:41 brent Exp Locker: brent $ SPRITE (Berkeley)";
  1005. d324 1
  1006. a324 1
  1007.       printf("OBJECTS stream %d (clt %d) file %d dir %d rmtFile %d\n",
  1008. d327 1
  1009. a327 1
  1010.         fsStats.object.rmtFiles);
  1011. d337 1
  1012. a337 1
  1013.       printf("HANDLES max %d exist %d scans %d looks %d scav %d (dirs %d)\n",
  1014. d339 1
  1015. @
  1016.  
  1017.  
  1018. 1.2
  1019. log
  1020. @Made file life time information a separate option.
  1021. Added statistics about object types and handle LRU
  1022. @
  1023. text
  1024. @d11 1
  1025. a11 1
  1026. static char rcsid[] = "$Header: /a/newcmds/fsstat/RCS/fsstat.c,v 1.1 88/12/02 09:05:53 brent Exp $ SPRITE (Berkeley)";
  1027. d37 1
  1028. a37 1
  1029. int printLifeTimes = FALSE;
  1030. d44 1
  1031. a44 1
  1032.     {OPT_TRUE, "L", (Address)&printLifeTimes, "Print file life-time info"},
  1033. d111 1
  1034. a111 1
  1035.     if (printLifeTimes) {
  1036. d115 1
  1037. a115 1
  1038.         printLifeTimes = 0;
  1039. d357 1
  1040. a357 1
  1041.    * ONLY FILE LIFE TIME STUFF BELOW HERE
  1042. d359 1
  1043. a359 1
  1044.   if (!printLifeTimes) {
  1045. @
  1046.  
  1047.  
  1048. 1.1
  1049. log
  1050. @Initial revision
  1051. @
  1052. text
  1053. @d11 1
  1054. a11 1
  1055. static char rcsid[] = "$Header: fsStat.c,v 1.14 88/09/26 17:23:54 douglis Exp $ SPRITE (Berkeley)";
  1056. d36 2
  1057. a37 1
  1058.     
  1059. d44 1
  1060. d56 1
  1061. d111 7
  1062. d119 1
  1063. a271 1
  1064.       register FsTypeStats *type = &fsStats.type;
  1065. a273 6
  1066.       int ratio;
  1067.       static char *typeStrings[] = { "temp", "swap", "obj", "bin", "other"};
  1068.       /*
  1069.        * # of columns for type-specific counts
  1070.        */
  1071.       unsigned int byteTotals[NUM_BYTE_COUNT_COLUMNS];
  1072. d275 1
  1073. a275 2
  1074.       printf(
  1075.            "Bytes:      cache     remote           disk       raw disk        devices\n");
  1076. d323 49
  1077. a371 1
  1078.    
  1079. @
  1080.